package org.texteasy;

import java.util.ArrayList;
import java.util.HashSet;

import org.texteasy.helpers.MessageEditorStates;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.CharArrayBuffer;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.Contacts;
import android.provider.Contacts.Groups;
import android.provider.Contacts.People;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;

public class BulkMessenger extends ListActivity implements DialogInterface.OnClickListener{
	
	private static final String TAG = "BulkMessenger";
	
	private final static int NEW_MESSAGE_ID = Menu.FIRST;
	private final static int DISPLAY_GROUP_ID = Menu.FIRST + 1;
	private final static int SELECT_ALL_ID = Menu.FIRST + 2;
	private final static int UNSELECT_ALL_ID = Menu.FIRST + 3;
	private final static int EDIT_SETTINGS = Menu.FIRST + 4;
	
	private static final int MESSAGE_CREATE=0;
	
	private String[] projection = new String[] {People._ID,People.NAME, People.TYPE, People.NUMBER};
	private String[] groupsProjection = new String[]{Groups._ID, Groups.SYSTEM_ID, Groups.NAME};
	private Uri contacts = People.CONTENT_URI;
	private HashSet<Long> selectedIds = new HashSet<Long>();
	private long selectedGroupId = -1;
	private static final String SELECTED_GROUP_ID_PREFERENCE = "SelectedGroupId";
	private int selectedGroupIndex;
	private ArrayList<Long> displayGroupIds;
	private TextEasyDBAdapter dbAdaptor;
	private AlertDialog groupDialog;
	
	static final int ID_COLUMN_INDEX = 0;
    static final int NAME_COLUMN_INDEX = 1;
    static final int TYPE_COLUMN_INDEX = 2;
    static final int NUMBER_COLUMN_INDEX = 3;
    
    private static final int GROUPS_COLUMN_INDEX_ID = 0;
    private static final int GROUPS_COLUMN_INDEX_SYSTEM_ID = 1;
    private static final int GROUPS_COLUMN_INDEX_NAME = 2;
	
    private static final int DISPLAY_GROUPS_ALL_CONTACTS = 0;
    private static final int DISPLAY_GROUPS_MY_CONTACTS = 1;
    
    //This will be set to true in onActivityResult, and will keep the selectedIds from
    //being set from the database in onResume
    private boolean skipSelectIdsOnResume = false;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        this.dbAdaptor = new TextEasyDBAdapter(this);
        this.dbAdaptor.open();
        
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        selectedGroupId = prefs.getLong(SELECTED_GROUP_ID_PREFERENCE, -1);
        
        boolean storeSelections = prefs.getBoolean(getString(R.string.REMEMBER_SELECTIONS), false);
        if(!storeSelections){
        	
        	if(getLastNonConfigurationInstance() != null){
        		this.selectedIds = (HashSet<Long>)getLastNonConfigurationInstance();
        	}
        }
        
        ListView listView = getListView();
        listView.setItemsCanFocus(false);
        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        listView.setTextFilterEnabled(true);
        queryContacts();
        
    }
    
    /**
     * Utility method for displaying querying contacts and displaying them 
     * @param nameClause
     */
    private void queryContacts(){
    	
    	Cursor managedCursor = managedQuery(contacts, projection, 
			getWhereClause(""), null, People.DEFAULT_SORT_ORDER);
    	
    	ResourceCursorAdapter contactsAdaptor = new ContactItemListAdapter(this, 
	    		R.layout.contacts_row,managedCursor);
    	setListAdapter(contactsAdaptor);
    }
    
    @Override
    protected void onPause() {
    	super.onPause();
    	
    	SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        boolean storeSelections = prefs.getBoolean(getString(R.string.REMEMBER_SELECTIONS), false);
        
        if(storeSelections){
	    	HashSet<Long> selectedIds = this.selectedIds;
	    	if(selectedIds != null && !selectedIds.isEmpty()){
	    		//this.dbAdaptor.persistSelectedIds(selectedIds);
	    	}
        }
    	
    	this.dbAdaptor.close();
    	
    	if(groupDialog != null && groupDialog.isShowing()){
    		groupDialog.dismiss();
    	}
    	
    }
    
    @Override
	protected void onDestroy() {
		super.onDestroy();
		
		if(this.dbAdaptor.isOpen()){
			this.dbAdaptor.close();
		}
	}

	@Override
    protected void onResume() {
    	super.onResume();
    	
    	this.dbAdaptor.open();
    	
    	SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        boolean storeSelections = prefs.getBoolean(getString(R.string.REMEMBER_SELECTIONS), false);
        if(storeSelections){
        	if(!skipSelectIdsOnResume){
        		//this.selectedIds = this.dbAdaptor.getSelectedIdsAndClear();	
        	}
        }
        
        ContactItemListAdapter adaptor =  (ContactItemListAdapter)getListAdapter();
        adaptor.notifyDataSetChanged();
    }
    
	@Override
	public Object onRetainNonConfigurationInstance() {
		
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        boolean storeSelections = prefs.getBoolean(getString(R.string.REMEMBER_SELECTIONS), false);
		
        if(!storeSelections){
        	return this.selectedIds;
        }else{
        	return null;
        }
	}
	
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(Menu.NONE, NEW_MESSAGE_ID, 0, R.string.NEW_MESSAGE);
        menu.add(Menu.NONE, DISPLAY_GROUP_ID, 1, R.string.DISPLAY_GROUPS);
        menu.add(Menu.NONE, SELECT_ALL_ID, 2, R.string.SELECT_ALL);
        menu.add(Menu.NONE, UNSELECT_ALL_ID, 3, R.string.UNSELECT_ALL);
        menu.add(Menu.NONE, EDIT_SETTINGS, 4, R.string.SETTINGS);
        return true;
    }
   
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
    	super.onListItemClick(l, v, position, id);
    	
    	HashSet<Long> selectedIds = this.selectedIds;
    	if(selectedIds.contains(id)){
    		selectedIds.remove(id);
    	}else{
    		selectedIds.add(id);
    	}
    }
    
    private String getWhereClause(String filter){
    	
    	String whereClause = People.NUMBER + " is not null and " + People.NAME + 
			" like '" + filter + "%'"; 
		
		long selectedGroupId = this.selectedGroupId;
		if(selectedGroupId >=0){
			whereClause += "AND People." + People._ID + " in " +
				"(SELECT person FROM groups, groupmembership WHERE ((groups._id=groupmembership.group_id OR " +
				"(groups._sync_account=groupmembership.group_sync_account AND groups._sync_id=groupmembership.group_sync_id))) " +
				"AND (GROUPS._ID = " + selectedGroupId + "))"; 
		}
    	return whereClause;
    }
    
    Cursor doFilter(String filter) {
    	final ContentResolver resolver = getContentResolver();
    	
    	return resolver.query(contacts, projection, 
    		getWhereClause(filter), null, People.DEFAULT_SORT_ORDER);
    }
    
    public void onClick(DialogInterface dialogInterface, int which){
    	
    	if (which == DialogInterface.BUTTON1) {
    		
    		if(selectedGroupIndex == DISPLAY_GROUPS_ALL_CONTACTS){
    			selectedGroupId = -1l;
    		}else{
    			selectedGroupId = this.displayGroupIds.get(selectedGroupIndex);
    		}
    		
    		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
    		prefs.edit().putLong(SELECTED_GROUP_ID_PREFERENCE, selectedGroupId).commit();
    		
    		this.selectedIds = new HashSet<Long>();
    		getListView().setFilterText("A");
    		getListView().clearTextFilter();
    	}else{
    		//user just selected an option
    		selectedGroupIndex = which;
    	}
    	
    }
    
    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
    	
    	switch (item.getItemId()) {
		case NEW_MESSAGE_ID:
			createNewMessage();
			break;
		case DISPLAY_GROUP_ID:
			createGroupAlertDialog();
			break;
		case SELECT_ALL_ID:
			selectAll();
			break;
		case EDIT_SETTINGS:
			startActivity(new Intent(this, TextEasyPreferences.class));  
			return(true); 
		case UNSELECT_ALL_ID:
			this.selectedIds = new HashSet<Long>();
			getListView().setFilterText("A");
			getListView().clearTextFilter();
			break;
		}
    	
    	return super.onMenuItemSelected(featureId, item);
    }
    
    private void selectAll(){
    	
    	//Log.e(TAG, "selectAll start");
    	
    	Cursor managedCursor = managedQuery(contacts, projection, 
			getWhereClause(""), null, People.DEFAULT_SORT_ORDER);
    	
    	//Log.e(TAG, "selectAll after query");
    	
    	HashSet<Long> selectedIds = this.selectedIds;
    	
    	while(managedCursor.moveToNext()){
    		
    		Long id = managedCursor.getLong(ID_COLUMN_INDEX);
    		
    		//if(!selectedIds.contains(id)){
    			selectedIds.add(id);
    		//}
    	}
    	
    	//Log.e(TAG, "selectAll after selection");
    	
    	getListView().setFilterText("A");
		getListView().clearTextFilter();
    	
		//Log.e(TAG, "after textFilter update");
		
    }
    
    private void createGroupAlertDialog(){

    	Cursor cursor = managedQuery(Groups.CONTENT_URI, 
			groupsProjection, null, null, Contacts.Groups.DEFAULT_SORT_ORDER);
		
    	ArrayList<CharSequence> groups = new ArrayList<CharSequence>();
    	ArrayList<Long> groupIds = new ArrayList<Long>();
    	
    	
    	groups.add(DISPLAY_GROUPS_ALL_CONTACTS,getString(R.string.ALL_CONTACTS_WITH_PHONES));
    	groupIds.add(DISPLAY_GROUPS_ALL_CONTACTS,-1l);
    	groups.add(DISPLAY_GROUPS_MY_CONTACTS,getString(R.string.GROUP_NAME_MY_CONTACTS));
    	
    	int selectedIndex = 0;
    	int i=2;
    	while(cursor.moveToNext()){
    		
    		String systemId = cursor.getString(GROUPS_COLUMN_INDEX_SYSTEM_ID);
            String name = cursor.getString(GROUPS_COLUMN_INDEX_NAME);
            Long groupId = cursor.getLong(GROUPS_COLUMN_INDEX_ID);
    		
            //Log.e(TAG, "_id: " + cursor.getLong(0) + " systemId: " + systemId + " name: " + name);
            if (cursor.isNull(GROUPS_COLUMN_INDEX_SYSTEM_ID) && 
        		!Groups.GROUP_MY_CONTACTS.equals(systemId)) {
            	groups.add(name);
            	groupIds.add(groupId);
            	if(selectedGroupId == groupId){
                	selectedIndex = i;
                }
            	i++;
            }else{
            	//found the "My Contacts" this displays weird (System Group: My Contacts)
            	//so gave it a different name above
            	groupIds.add(DISPLAY_GROUPS_MY_CONTACTS,groupId);
            	if(selectedGroupId == groupId){
            		selectedIndex = DISPLAY_GROUPS_MY_CONTACTS;
                }
            }
    	}
		
    	this.displayGroupIds = groupIds;
    	CharSequence[] displayGroups = groups.toArray(new CharSequence[groups.size()]);

    	groupDialog = new AlertDialog.Builder(this)
	        .setTitle(R.string.SELECT_GROUP_TITLE)
	        .setPositiveButton(android.R.string.ok, this)
	        .setNegativeButton(android.R.string.cancel, null).
	        setSingleChoiceItems(displayGroups,
                    selectedIndex, this).create();
    	groupDialog.show();
    }
    
    private void createNewMessage(){
    	
    	
    	//Log.e(TAG, "start createNewMessage");
    	
    	HashSet<Long> selectedIds = this.selectedIds;

    	if(!selectedIds.isEmpty()){
    		
    		//Log.e(TAG, "before query createNewMessage");
	    	
	    	/*Uri contacts = People.CONTENT_URI;
	        
	        Cursor managedCursor = managedQuery(contacts, this.projection, 
	    		"PEOPLE." + People._ID + inStatement, null, People.DEFAULT_SORT_ORDER);
	    	
	        //Log.e(TAG, "before iterating createNewMessage");
	        final Resources resources = getResources();
	        String[] localizedLabels = resources.getStringArray(android.R.array.phoneTypes);
	        String[] names = new String [selectedIds.size()];
	        String[] labels = new String[selectedIds.size()];
	        String[] numbers = new String[selectedIds.size()];
	        int count = 0;
	        if(managedCursor != null){
	        	while(managedCursor.moveToNext()){
	        		numbers[count] = managedCursor.getString(NUMBER_COLUMN_INDEX);
	        		names[count] = managedCursor.getString(NAME_COLUMN_INDEX);
	        		
	        		if(!managedCursor.isNull(TYPE_COLUMN_INDEX)){
	        			int type = managedCursor.getInt(TYPE_COLUMN_INDEX);
	        			if (type != People.Phones.TYPE_CUSTOM) {
	        				labels[count] = localizedLabels[type - 1];
	        				try {
	        					labels[count] = localizedLabels[type - 1];
	                        } catch (ArrayIndexOutOfBoundsException e) {
	                        	labels[count] = localizedLabels[People.Phones.TYPE_HOME - 1];
	                        }
	        			}
	        		}else{
	        			labels[count] = "";
	        		}
	        		count++;
	        	}
	        }
	        
	        managedCursor.close();
	        //Log.e(TAG, "after query createNewMessage");
	        */
	        
	        Intent intent = new Intent(this, MessageEditor.class);
	        intent.putExtra(MessageEditor.CONTACT_IDS, selectedIds);
	        intent.putExtra(MessageEditor.MESSAGE_EDITOR_STATE, 
        		MessageEditorStates.NEW_MESSAGE_LOADING.getName());
	        startActivityForResult(intent, MESSAGE_CREATE);
	        /*String numbers = buffer.substring(0, buffer.length() - 1);
	        Intent i = new Intent();
	        i.setAction(Intent.ACTION_VIEW);
	        i.setType("vnd.android-dir/mms-sms");
	        i.putExtra("address", numbers);
	        
	        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
	        String signature = prefs.getString(getString(R.string.ADD_SIGNATURE_TITLE), "");
	        if(signature != null && !signature.equals("")){
	        	i.putExtra("sms_body", "\n" + signature);
	        }
	        
	        //Log.e(TAG, "starting mms activity");
	        
	        startActivity(i);*/
    	}
    	
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    	super.onActivityResult(requestCode, resultCode, data);
    	
    	Log.e(TAG, "onActivityResult");
    	if(requestCode == MESSAGE_CREATE){
    		
    		skipSelectIdsOnResume = true;
    		
    		if(resultCode == RESULT_OK){
    			
    			this.selectedIds = (HashSet<Long>)data.getExtras().
    				getSerializable(MessageEditor.CONTACT_IDS);
    			
    		}else{
    			this.selectedIds = new HashSet<Long>();
    		}
    		
    	}else{
    		throw new IllegalArgumentException("Unknown request code: " + requestCode);
    	}
    }
    
    final static class ContactListItemCache {
    	public TextView nameView;
        public CharArrayBuffer nameBuffer = new CharArrayBuffer(128);
        public TextView labelView;
        public CharArrayBuffer labelBuffer = new CharArrayBuffer(128);
        public TextView numberView;
        public CharArrayBuffer numberBuffer = new CharArrayBuffer(128);
        public CheckBox checkBox;
        public boolean checked;
        
        
    }
    
    private final class ContactItemListAdapter extends ResourceCursorAdapter{

    	private CharSequence[] mLocalizedLabels;
    	private CharSequence mUnknownNameText;
    	
    	public ContactItemListAdapter(Context context, int resource, Cursor cursor){
    		super(context, resource, cursor);
    		
    		final Resources resources = context.getResources();
    		mLocalizedLabels = resources.getStringArray(android.R.array.phoneTypes);
    		
    		mUnknownNameText = context.getText(android.R.string.unknownName);
    	}
    	
    	@Override
    	public View newView(Context context, Cursor cursor, ViewGroup parent) {
    		final View view = super.newView(context, cursor, parent);

            final ContactListItemCache cache = new ContactListItemCache();
            cache.nameView = (TextView) view.findViewById(R.id.name);
            cache.labelView = (TextView) view.findViewById(R.id.label);
            cache.labelView.setCompoundDrawablePadding(3);
            cache.numberView = (TextView) view.findViewById(R.id.number);
            cache.checkBox = (CheckBox)view.findViewById(R.id.selected);
            view.setTag(cache);

            return view;
    		
    	}
    	
    	 @Override
         public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
    		 return doFilter(constraint.toString());
         }
    	
		@Override
		public void bindView(View view, Context context, Cursor cursor) {
			
			final ContactListItemCache cache = (ContactListItemCache) view.getTag();
			
			// Set the name           
            cursor.copyStringToBuffer(NAME_COLUMN_INDEX, cache.nameBuffer);
            int size = cache.nameBuffer.sizeCopied;
            if (size != 0) {
                cache.nameView.setText(cache.nameBuffer.data, 0, size);
            } else {
                cache.nameView.setText(mUnknownNameText);
            }
            
            //Set the phone number
            TextView numberView = cache.numberView;
            cursor.copyStringToBuffer(NUMBER_COLUMN_INDEX, cache.numberBuffer);
            size = cache.numberBuffer.sizeCopied;
            if (size != 0) {
                numberView.setText(cache.numberBuffer.data, 0, size);
                numberView.setVisibility(View.VISIBLE);
            } else {
                numberView.setVisibility(View.GONE);
            }
            
            // Set the label
            TextView labelView = cache.labelView;
            if (!cursor.isNull(TYPE_COLUMN_INDEX)) {
                int type = cursor.getInt(TYPE_COLUMN_INDEX);

                if (type != People.Phones.TYPE_CUSTOM) {
                    try {
                        labelView.setText(mLocalizedLabels[type - 1]);
                    } catch (ArrayIndexOutOfBoundsException e) {
                        labelView.setText(mLocalizedLabels[People.Phones.TYPE_HOME - 1]);
                    }
                } else {
                	// Set the text to a length of 0
                    labelView.setText(cache.labelBuffer.data, 0, 0);
                }
            } else {
                // Set the text to a length of 0
                labelView.setText(cache.labelBuffer.data, 0, 0);
            }
            
            long contactId = cursor.getLong(ID_COLUMN_INDEX);
            if(selectedIds.contains(contactId)){
            	cache.checkBox.setChecked(true);
            }else{
            	cache.checkBox.setChecked(false);
            }
            
		}
    	
    }
    
}